(function($) {
    var $document = $(document);
    // prevent multiple loading
    if (typeof $.remoteHandler !== 'undefined') {
        $.error('Remote handler has already been loaded');
    }

    var remoteHandler;
    $.remoteHandler = remoteHandler = {
        linkClickSelector: 'a[data-remote]',
        formSubmitSelector: 'form[data-remote]',
        inputClickSelector: 'form[data-remote] input[type=submit], form[data-remote] input[type=image],' +
                'form[data-remote] button[type=submit], form[data-remote] button:not([type])',

        fire: function($obj, name, data) {
            var e = $.Event(name);
            $obj.trigger(e, data);
            return e.result !== false;
        },
        send: function($obj, url, method, data, dataType) {
            $.ajax({
                url: url,
                type: method,
                data: data,
                dataType: dataType,
                beforeSend: function(xhr, settings) {
                    utils.clearFlash();
                    if ($obj.data('confirm') && !confirm($obj.data('confirm'))) {
                        return false;
                    }

                    if (remoteHandler.fire($obj, 'ajax:beforeSend', [xhr, settings])) {
                        $obj.trigger('ajax:send', xhr);
                    } else {
                        return false;
                    }
                    $obj.attr('disabled', 'disabled');
                },
                success: function(data, status, xhr) {
                    switch (dataType) {
                        case 'html':
                            var container = $obj.data('container') || '#main';
                            var $container = $(container);
                            if ($container.length > 0) {
                                $container.html(data);
                                remoteHandler.addHistory(url, xhr);
                                utils.showCkeditor();
                                utils.autoFocus();
                                utils.initCommon();
                            }
                            break;
                        case 'js':
                            $.globalEval(data);
                            break;
                        default:
                    }
                    
                    $obj.trigger('ajax:success', [data, status, xhr]);
                },
                error: function(xhr, status, error) {
                    $obj.trigger('ajax:error', [xhr, status, error]);
                },
                complete: function(xhr, status) {
                    $obj.trigger('ajax:complete', [xhr, status]);
                    $obj.removeAttr('disabled');
                },
                error: function (xhr, ajaxOptions, thrownError) {
                    $("#error-modal").modal('show');
                }
            });
        },
        bind: function() {
            $document.on('click.remote', remoteHandler.linkClickSelector, function(e) {
                e.preventDefault();
                var $this = $(this);
                var data = $this.data('params') || null;
                var dataType = $this.data('type') || 'html';
                var method = $this.data('method') || 'get';
                var url = $this.attr('href');
                remoteHandler.send($this, url, method, data, dataType);
            });

            $document.on('submit.remote', remoteHandler.formSubmitSelector, function(e) {
                e.preventDefault();
                var $this = $(this);
                var data = $this.serializeArray();
                var dataType = $this.data('type') || 'html';
                var method = $this.attr('method');
                var url = $this.attr('action');
                remoteHandler.send($this, url, method, data, dataType);
            });

            $document.on('click.remote', remoteHandler.inputClickSelector, function(e) {
                
            });
        },
        addHistory: function(url, xhr) {
            if (history && typeof history.replaceState === 'function') {
                var title = xhr.getResponseHeader('X-Page-Title');
                history.replaceState({}, title, url);
                if (title) {
                    document.title = title;
                }
            }
        }
    };
    remoteHandler.bind();

    if (typeof $.utils !== 'undefined') {
        $.error('Utils has already been defined');
    }

    /**
     * misc. utilities for updating page content in common scenarios
     */
    var utils;
    $.utils = utils = {
        focusableSelector: 'input[type=text]:visible, input[type=search]:visible, input[type=email]:visible,' +
                'input[type=password]:visible, input[type=phone]:visible, input[type=radio]:visible, input[type=checkbox]:visible,' +
                'select:visible, textarea:visible',

        /**
         * automatically focus on the first visible input field
         * @param string formId form id to search for (optional)
         * @param string inputFilter additional filter for input (optional)
         */
        autoFocus: function(formId, inputFilter) {
            var $form;
            if (typeof formId === 'string') {
                $form = $('form#' + formId);
            } else {
                $form = $('form:first');
            }
            if ($form.length > 0) {
                var $field = $form.find(utils.focusableSelector);
                if (typeof inputFilter === 'string') {
                    $field = $field.filter(inputFilter);
                }
                $field.eq(0).focus();
            }
        },

        /**
         * clear all errors of the form
         * @param string formId (optional)
         */
        clearFieldError: function(formId) {
            var $form = $('#' + formId);
            $form.find('.form-group.has-error').removeClass('has-error');
            $form.find('.input-error').removeClass('input-error');
            $form.find('.text-danger').remove();
        },

        /**
         * clear all flash message
         */
        clearFlash: function() {
            $('.flash').children('.alert').remove();
        },

        /**
         * show form field error that look nice on twbs form structure
         * @param string formId
         * @param string field (input name)
         * @param string msg
         */
        showFieldError: function(formId, field, msg) {
            var $form = $('#' + formId);
            var $field = $form.find('[name=' + field + ']');
            if ($field.length > 0) {
                if ($field.parents('.input-group').length > 0) {
                    $field.addClass('input-error').parents('.form-group').addClass('has-error');
                    $field.parents('.input-group').after('<div class="text-danger">' + msg + '</div>');
                } else {
                    $field.addClass('input-error').after('<div class="text-danger">' + msg + '</div>').parents('.form-group').addClass('has-error');    
                }
            }
        },

        /**
         * show flash message
         * @param string msg
         * @param string klass Flash class (e.g. alert-danger in twbs)
         */
        showFlash: function(msg, klass) {
            utils.clearFlash();
            $('.flash').html(
                '<div class="alert ' + klass + '">' +
                    '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' +
                    msg +
                '</div>'
            );
            setTimeout(function() {
                utils.clearFlash();
            }, timeOutNumber);
            
        },
        
        showAlertModal: function (title, msg) {
            if (typeof title != 'underfined') {
                $("#alert-modal .modal-title").html(title);
            }
            $("#alert-modal .modal-body").html(msg);
            $("#alert-modal").modal('show');
        },
        
        removeIconErrorTab: function() {
            $('.icon-error-tab').remove();
        },
        focusErrorTab: function(error_fields) { // nav_tabs: is Class, field_error: is ID
            if (error_fields.length > 0) {
                // Remove error icon for tab
                utils.removeIconErrorTab();
                
                // Remove error icon for tab
                for (index_field in error_fields) {
                    var id_tab_parent = $("#" + error_fields[index_field]).parents('.tab-pane').eq(0).attr('id');
                    var $tab = $("a[href='#" + id_tab_parent + "']");
                    if ($tab.find('.icon-error-tab').length == 0) {
                        var old_value = $tab.html();
                        $tab.html("<i class='fa fa-warning icon-error-tab'></i>" + old_value);
                    }
                    
                }
                
                //Focus first error tab
                $(".nav-tabs li").removeClass('active');
                $(".tab-pane").removeClass('active');
                var id_first_tab_parent = $("#" + error_fields[0]).parents('.tab-pane').eq(0).attr('id');
                $("a[href='#" + id_first_tab_parent + "']").parent('li').addClass('active');
                $("#" + id_first_tab_parent).addClass('active');    
            }
        },
        
        initCommon: function() {
            // Set tooltip
            $('.has-tooltip').tooltip({
                placement: 'top'
            });

        },
    };
    
    /**
     * Admin login (normal)
     */
    
    $document.on({
        'ajax:beforeSend': function() {
            $.utils.clearFieldError('form-admin-login');
            $(this).find('.btn').attr('disabled', 'disabled');
        },
        'ajax:success': function(e, data) {
            if (data.status) {
                if (typeof data.redirect != '') {
                    window.location.href = data.redirect;
                } else {
                    window.location.reload();
                }
                
            } else {
                if (data.code === 'invalid_data') {
                    for (var field in data.messages) {
                        $.utils.showFieldError('form-admin-login', field, data.messages[field][0]);
                    }
                    $.utils.autoFocus('form-admin-login', '.input-error');
                    $('#loginerror').text('');
                }
                else {
                    $('#loginerror').text(data.message);
                }
                
            }
        },
        'ajax:complete': function() {
            $(this).find('.btn').removeAttr('disabled');
        }

    }, '#form-admin-login');
    
})(jQuery);